/** 
 * AST walker that creates a new AST that doesn't contain seeds that are not used,
 * and does semantic validation such as detecting seeds that are not 4/4 length.
 *
 * @author talgiat
 */
tree grammar AmFmOptimizer;
options {
 tokenVocab=AmFm;
 ASTLabelType=CommonTree;
 output=AST;
}
@header{
/*
 * Copyright 2009, Team Mondegreen:
 * Brian Hsieh - bh2181@columbia.edu
 * Eugene Yao - eyy2102@columbia.edu
 * Jake Amonette - jaa2149@columbia.edu
 * Tal Giat - tg2235@colubia.edu
 * 
 * This file is part of AMFM (A Minimal Fractal Music Language), a language created for
 * fractal music as part of the Programming Languages and Translator class at Columbia university.
 *
 * For more details go to: http://code.google.com/p/amfm/
 * 
 * AMFM is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * at your option any later version.
 * 
 * AMFM is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with AMFM.  If not, see <http://www.gnu.org/licenses/>. 
 */

package org.mondegreen.amfm.compiler;

import java.util.Set;
}
@members {
private Set<String> usedSeeds;

public void setUsedSeeds(Set<String> usedSeeds) {
  this.usedSeeds = usedSeeds;
}
}

// AMFM program 
program: ^(PROGRAM seed+ start_func);

// Seeds rules
seed  : ^(ID INSTRUMENT note_unit+) -> {usedSeeds == null || usedSeeds.contains($ID.text)}? ^(ID INSTRUMENT note_unit+) 
                             -> ; /* Remove seed node if it is not used (but only if the used lookup was set) */
note_unit : ^(NOTEUNIT ^(NOTE note) (duration volume?)?) | ^(NOTEUNIT REST duration?);
duration: FRACTION | number;
volume  : VOLUME_LEVELS_MINUS_F | 'F';
note :  note_letter octave? ; 
note_letter: NOTELETTERS_WITH_ACCIDENTAL_MINUS_F | 'F'ACCIDENTAL?;
octave: ONE_TO_NINE;

// Start function
start_func:  ^(START function*);
function: (play | ss_func);
play: ^(PLAY func_params);
ss_func: ^(ss_func_name ss_func_params);
ss_func_name: (SS_PITCH | SS_VOLUME | SS_RHYTHM | SS_PITCH_VOLUME | SS_PITCH_RHYTHM | SS_RHYTHM_VOLUME | SS_ALL);
ss_func_params: func_params BOOLEAN;
func_params: ID start_bar num_of_bars; 
start_bar: number ;
num_of_bars: number ;
number  : ONE_TO_NINE | TEN_AND_UP;